package bb.lanxing.util.log;

import static bb.lanxing.common.config.Constants.LOG_DELETE_DAYS;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import com.blankj.utilcode.util.DeviceUtils;
import com.orhanobut.logger.DiskLogStrategy;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import androidx.annotation.NonNull;

import bb.lanxing.util.AppFileUtils;

public class CustomDiskLogStrategy extends DiskLogStrategy {
    public static final int MAX_BYTES = 500 * 1024; // 500K averages to a 4000 lines per file

    public CustomDiskLogStrategy(@NonNull Handler handler) {
        super(handler);
    }

    public static class WriteHandler extends Handler {

        @NonNull
        private final String folder;
        private final int maxFileSize;

        public WriteHandler(@NonNull Looper looper, @NonNull String folder, int maxFileSize) {
            super(looper);
            this.folder = folder;
            this.maxFileSize = maxFileSize;
        }

        @Override
        public void handleMessage(@NonNull Message msg) {
            String content = (String) msg.obj;
            AppFileUtils.deleteOldFile(LOG_DELETE_DAYS, folder);
            FileWriter fileWriter = null;
            File logFile = getLogFile(folder, "model_" + DeviceUtils.getModel() + "_logs");

            try {
                fileWriter = new FileWriter(logFile, true);

                writeLog(fileWriter, content);

                fileWriter.flush();
                fileWriter.close();
            } catch (IOException e) {
                if (fileWriter != null) {
                    try {
                        fileWriter.flush();
                        fileWriter.close();
                    } catch (IOException e1) {
                        /* fail silently */ }
                }
            }
        }

        /**
         * This is always called on a single background thread.
         * Implementing classes must ONLY write to the fileWriter and nothing more.
         * The abstract class takes care of everything else including close the stream and catching IOException
         *
         * @param fileWriter an instance of FileWriter already initialised to the correct file
         */
        private void writeLog(@NonNull FileWriter fileWriter, @NonNull String content) throws IOException {
            fileWriter.append(content);
        }

        private File getLogFile(@NonNull String folderName, @NonNull String fileName) {

            File folder = new File(folderName);
            File parentFile = folder.getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }
            if (!folder.exists()) {
                // TODO: What if folder is not created, what happens then?
                folder.mkdirs();
            }

            int newFileCount = 0;
            File newFile;
            File existingFile = null;

            newFile = new File(folder, String.format("%s_%s.csv", fileName, newFileCount));
            while (newFile.exists()) {
                existingFile = newFile;
                newFileCount++;
                newFile = new File(folder, String.format("%s_%s.csv", fileName, newFileCount));
            }

            if (existingFile != null) {
                if (existingFile.length() >= maxFileSize) {
                    return newFile;
                }
                return existingFile;
            }

            return newFile;
        }
    }
}
